<script lang="ts">
    import {bem} from "@/common/util";
    import mixin from "@/uni_modules/u-tools/mixin/mixin";
    import mpMixin from "@/uni_modules/u-tools/mixin/mpMixin";
    import props from "./props";
    import UText from "@/uni_modules/u-text/components/u-text/u-text.vue";

    export default {
        name: "u-textarea",
        // 组件
        components: {UText},
        // 混合
        mixins: [props, mixin, mpMixin],
        // 事件
        emits: ["update:value", "input", "focus", "blur", "confirm", "keyboardHeightChange", "lineChange", "onload", "clear"],
        // 数据
        data()
        {
            return {
                // 当前输入框的值
                textareaValue: "",
                // 文本域是否获取焦点
                isFocus: false
            };
        },
        // 监听器
        watch: {
            // 监听输入框的值
            value(value: string | number | null): void
            {
                this.textareaValue = value != null ? value.toString() : "";
            }
        },
        // 页面挂载
        mounted()
        {
            // 组件挂载完成
            this.$nextTick(() =>
            {
                // 获取当前输入框的值
                this.textareaValue = this.value != null ? this.value.toString() : "";

                // 判断是否触发input事件
                if (this.trigger)
                {
                    // 触发自定义input事件
                    this.$emit("input", this.textareaValue);
                }

                // 触发onload事件
                this.$emit("onload", this.textareaValue);
            });
        },
        // 计算函数
        computed: {
            // 生成bem风格的类名
            bemClass(): string
            {
                return bem("textarea", [
                    `border-${this.border}`,
                    this.disabled ? "disabled" : "",
                    SizeTypeMap.includes(this.radius.toString()) ? `radius-${this.radius}` : ""
                ]);
            },
            // 获取按钮圆角
            getRadius(): string
            {
                let radius = "";

                // 判断是否为指定大小的圆角
                if (!SizeTypeMap.includes(this.radius.toString()))
                {
                    radius = this.$u.unit(this.radius);
                }

                return radius;
            },
            // 获取清除按钮状态
            getClearStatus(): boolean
            {
                return this.clearable && this.isFocus && this.textareaValue !== "" && !this.disabled && !this.readonly;
            }
        },
        // 方法
        methods: {
            // 键盘输入时触发事件
            inputHandler(event: Record<string, any>): void
            {
                // 缓存当前值
                this.textareaValue = event.detail?.value;

                // 触发内容变化事件方法
                this.valueChange();

                // 阻止冒泡
                this.stop && this.stopPropagation(event);

                // 阻止事件默认行为
                this.prevent && this.preventDefault(event);
            },
            // 键盘完成时触发事件
            confirmHandler(event: Record<string, any>): void
            {
                // 触发键盘完成事件
                this.$emit("confirm", this.getOutputValue());

                // 阻止冒泡
                this.stop && this.stopPropagation(event);

                // 阻止事件默认行为
                this.prevent && this.preventDefault(event);
            },
            // 获取焦点时触发事件
            focusHandler(event: Record<string, any>): void
            {
                // 设置获取焦点
                this.isFocus = true;

                // 触发获取焦点事件
                this.$emit("focus", this.getOutputValue());

                // 阻止冒泡
                this.stop && this.stopPropagation(event);

                // 阻止事件默认行为
                this.prevent && this.preventDefault(event);
            },
            // 失去焦点时触发事件
            blurHandler(event: Record<string, any>): void
            {
                // H5端的blur会先于点击清除控件的点击click事件触发，导致focus瞬间为false，从而隐藏了清除控件而无法被点击到
                asyncFn(() =>
                {
                    this.isFocus = false;
                }, 180).finally(() =>
                {
                });

                // 触发失去焦点事件
                this.$emit("blur", this.getOutputValue());

                // 阻止冒泡
                this.stop && this.stopPropagation(event);

                // 阻止事件默认行为
                this.prevent && this.preventDefault(event);
            },
            // 键盘高度发生变化时触发事件
            keyboardHeightChangeHandler(event: Record<string, any>): void
            {
                // 触发键盘高度变化事件
                this.$emit("keyboardHeightChange", this.getOutputValue());

                // 阻止冒泡
                this.stop && this.stopPropagation(event);

                // 阻止事件默认行为
                this.prevent && this.preventDefault(event);
            },
            // 行数发生变化时触发事件
            lineChangeHandler(event: Record<string, any>): void
            {
                // 当前行数
                const {lineCount} = event.detail || {};

                this.$emit("lineChange", this.getOutputValue(), lineCount);
            },
            // 点击清除按钮时触发事件
            clearHandler(): void
            {
                // 清空当前值
                this.textareaValue = "";

                // 触发内容变化事件方法
                this.valueChange();

                // 触发清除事件
                this.$emit("clear", "");
            },
            // 内容发生变化时的处理函数
            valueChange(): void
            {
                this.$nextTick(() =>
                {
                    // 当前输出的值
                    const outputValue = this.getOutputValue();

                    // 触发输入事件
                    this.$emit("input", outputValue);

                    // 触发双向绑定事件
                    this.$emit("update:value", outputValue);
                });
            },
            // 输出值的转化
            getOutputValue(): string | number
            {
                let value: string | number = this.textareaValue;

                // 是否trim
                if (this.trim)
                {
                    value = value.trim();
                }

                return value;
            }
        }
    };
</script>

<template>
    <!-- 输入框组件 -->
    <view
        :class="[
            customClass,
            bemClass
        ]"
        :name="name"
        :style="[
            customStyle,
            {'--custom-textarea-radius': getRadius},
            {'--custom-textarea-background-color': backgroundColor},
            {'--custom-textarea-disabled-background-color': disabledColor},
            {'--custom-textarea-border-color': borderColor},
            {'--custom-textarea-color': color},
            {'--custom-textarea-font-size': $u.unit(fontSize)},
            {'--custom-textarea-text-align': textAlign},
            {'--custom-textarea-height': autoHeight ? 'auto' : $u.unit(height)}
        ]"
    >
        <!-- 文本域 -->
        <view class="textarea-wrapper">
            <textarea
                :adjust-position="adjustPosition"
                :auto-blur="autoBlur"
                :auto-focus="autoFocus"
                :auto-height="autoHeight"
                :confirm-hold="confirmHold"
                :confirm-type="confirmType"
                :cursor="cursor"
                :cursor-color="cursorColor"
                :cursor-spacing="cursorSpacing"
                :disabled="disabled || readonly"
                :fixed="fixed"
                :focus="focus"
                :hold-keyboard="holdKeyboard"
                :ignore-composition-event="ignoreCompositionEvent"
                :inputmode="inputMode"
                :maxlength="maxlength"
                :placeholder="placeholder"
                :placeholder-class="placeholderClass"
                :placeholder-style="placeholderStyle"
                :selection-end="selectionEnd"
                :selection-start="selectionStart"
                :value="textareaValue"
                class="textarea"
                @blur="blurHandler"
                @confirm="confirmHandler"
                @focus="focusHandler"
                @input="inputHandler"
                @keyboardheightchange="keyboardHeightChangeHandler"
                @linechange="lineChangeHandler"
            />
        </view>
        <!-- //文本域 -->

        <!-- 清除以及文本统计 -->
        <view
            v-if="getClearStatus || count"
            class="operation"
        >
            <!-- 清除按钮 -->
            <view class="clear">
                <!-- 内盒 -->
                <view
                    v-if="getClearStatus"
                    class="clear-wrapper"
                    @tap.stop="clearHandler"
                >
                    <u-text
                        :font-size="12"
                        :gap="2"
                        :line-height="20"
                        :prefix-icon-size="14"
                        color="#909193"
                        prefix-icon="delete"
                        prefix-icon-color="#909193"
                        text="清空"
                    />
                </view>
                <!-- //内盒 -->
            </view>
            <!-- //清除按钮 -->

            <!-- 文本统计 -->
            <view class="count">
                <!-- 内盒 -->
                <view
                    v-if="count"
                    class="count-wrapper"
                >
                    <u-text
                        :font-size="12"
                        :line-height="20"
                        :tabular="true"
                        :text="textareaValue.length + '/' + maxlength"
                        color="#909193"
                        justify-content="flex-end"
                    />
                </view>
                <!-- //内盒 -->
            </view>
            <!-- //文本统计 -->
        </view>
        <!-- //清除以及文本统计 -->
    </view>
    <!-- //输入框组件 -->
</template>

<style lang="scss" scoped>
    $u-textarea-wrapper-border-color: #c8c9cc !default;
    $u-textarea-clear-background-color: #c6c7cb !default;

    .u-textarea
    {
        display: flex;
        flex-direction: column;
        box-sizing: border-box;
        padding: 9px;
        border-radius: var(--custom-textarea-radius);
        background-color: var(--custom-textarea-background-color);

        // 文本域外框
        .textarea-wrapper
        {
            flex: 1;

            // 文本控件
            .textarea
            {
                font-size: var(--custom-textarea-font-size);
                line-height: 20px;
                width: 100%;
                height: var(--custom-textarea-height);
                text-align: var(--custom-textarea-text-align);
                color: var(--custom-textarea-color, $theme-main-text-color);
            }

            // placeholderStyle样式名称
            :deep(.textarea-placeholder)
            {
                font-size: var(--custom-textarea-font-size);
                font-weight: normal;
                color: $theme-para-text-color;
            }
        }

        // 清除以及统计
        .operation
        {
            display: flex;
            align-items: center;
            justify-content: space-between;
            margin-top: 5px;
        }

        // 超小尺寸圆角
        &.u-textarea-radius-mini
        {
            border-radius: $border-radius-mini;
        }

        // 小尺寸圆角
        &.u-textarea-radius-small
        {
            border-radius: $border-radius-small;
        }

        // 普通尺寸圆角
        &.u-textarea-radius-normal
        {
            border-radius: $border-radius-normal;
        }

        // 大尺寸圆角
        &.u-textarea-radius-large
        {
            border-radius: $border-radius-large;
        }

        // 四边框
        &-border-surround
        {
            border: 1px solid var(--custom-textarea-border-color, $u-textarea-wrapper-border-color);
        }

        // 底部边框
        &-border-bottom
        {
            border-bottom: 1px solid var(--custom-textarea-border-color, $u-textarea-wrapper-border-color);
            border-radius: 0 !important;
        }

        // 无边框
        &-border-none
        {
            border: none;
            padding: 0;
        }

        // 禁用
        &-disabled
        {
            pointer-events: none;
            background-color: var(--custom-textarea-disabled-background-color);

            // 文本框
            .textarea-wrapper
            {
                // 文本控件
                .textarea
                {
                    color: rgba(192, 196, 204, 1);
                }

                // placeholderStyle样式名称
                :deep(.textarea-placeholder)
                {
                    color: rgba(192, 196, 204, 1);
                }
            }
        }
    }
</style>